import * as bluebird from 'bluebird';
import { Service } from 'egg';
import * as _ from 'lodash';
import {promisify} from 'util';

export default class CustomerService extends Service {
  /**
   * 客户重建索引
   * @param data
   */
  public async rebuildIndex(data: any) {
    const {ctx, app} = this;
    const result: any = {
      success: false,
    };
    try {
      // 查询要处理的账户
      // 定义查询条件
      let query = {};
      if (data && data.account) {
        if (typeof (data.account) === 'string') {
          query = {_id: data.account + '_cc'};
        }
        if (typeof (data.account) === 'object') {
          let ids: any = [];
          for (const id of data.account) {
            ids.push(id + '_cc');
          }
          ids = _.uniq(ids);
          query = {_id: {$in: ids}};
        }
      }
      // 定义返回字段
      const returnFields = {
        account: 1,
        dataDB: 1,
        readEs: 1,
      };
      const accountDocs: any[] = [];
      const accountCursor = await app.commonDB.db(app.constants.BILL).collection(app.constants.DB_PLATFORM_ACCOUNT_PRODUCT)
        .find(query, {projection: returnFields});
      while (await accountCursor.hasNext()) {
        const accountTemp = await accountCursor.next();
        if (accountTemp.dataDB && !accountTemp.readEs) {
          accountDocs.push(accountTemp);
        }
      }
      ctx.logger.info('---------rebuildIndex-----get account----size----' + accountDocs.length);
      // 如果没有account直接返回
      if (accountDocs.length < 1) {
        result.success = true;
        result.message = 'not_find_account';
        return result;
      }
      // 处理数据
      await this._handleAccountData(accountDocs);
      result.success = true;
    } catch (e) {
      ctx.logger.error('---------rebuildIndex-----error----' + e);
    }
    return result;
  }

  /**
   * 处理账户数据
   * @param docs
   * @private
   */
  private async  _handleAccountData(docs: any[]) {
    const { ctx, app} = this;
    try {
      await bluebird.Promise.mapSeries(docs, async (accountDoc) => {
        ctx.logger.info('---------_handleAccountData ******* begin ****** 处理account---- ' + accountDoc.account);
        const customer: any = await app.commonDB.db(accountDoc.dataDB).collection(accountDoc.account + app.constants.DB_CUSTOMER)
          .findOne({}, {projection: {_id: 1}});
        if (!customer) {
          ctx.logger.info('---------_handleAccountData----- ' + accountDoc.account + ' -- 客户数据为0， 跳到下一个账户！！！！---- ');
          await app.commonDB.db(app.constants.BILL).collection(app.constants.DB_PLATFORM_ACCOUNT_PRODUCT)
            .updateOne({_id: accountDoc._id}, {$set: {readEs: true}});
          return;
        }
        // 查询该账户下的customer数据
        const returnFields: any = {
          _id: 1,
          accountId: 1,
          name: 1,
          phone: 1,
          notifyTime: 1,
          createTime: 1,
        };
        let customerArray: any[] = [];
        let count: number = 0;
        /**
         * // todo 账户客户巨大
         * // if (accountDoc.account === 'N00000007003') {
         * //   return;
         * // }
         * 2016-10-25 13:32:51   2018-07-14 18:08:51
         *    2016-10-25 00:00:00  2017-04-14 00:00:00
         *    2017-04-14 00:00:00  2017-10-14 00:00:00
         *    2017-10-14 00:00:00  2018-05-01 00:00:00
         *    2018-05-01 00:00:00  2021-01-08 00:00:00
         *
         */
        // const customerCursor = await app.commonDB.db(accountDoc.dataDB).collection(accountDoc.account + app.constants.DB_CUSTOMER)
        //   .find({createTime: { $gte: '2018-05-01 00:00:00', $lt: '2021-01-08 00:00:00'}},
        //     {sort: {createTime: -1}, projection: returnFields});
        const customerCursor = await app.commonDB.db(accountDoc.dataDB).collection(accountDoc.account + app.constants.DB_CUSTOMER)
          .find({}, {projection: returnFields});
        while (await customerCursor.hasNext()) {
          const customerTemp = await customerCursor.next();
          customerTemp.accountId = !customerTemp.accountId ? accountDoc.account : customerTemp.accountId;
          customerArray.push(customerTemp);
          if (customerArray.length >= 4500) {
            ++count;
            // 重建索引
            await this._rebuildCustomerIndex(customerArray);
            ctx.logger.info('---------_handleAccountData ******* rebuildCustomerIndex ****** 完成了 ---- ' + 4500 * count);
            customerArray = [];
          }
        }
        if (customerArray.length > 0) {
          // 剩下的重建索引
          ctx.logger.info('---------_handleAccountData ******* rebuildCustomerIndex ****** 完成剩下的 ---- ' + customerArray.length);
          await this._rebuildCustomerIndex(customerArray);
        }
        // 验证数据,先暂停1秒钟，让分片数据完全写完
        const result: any = await this.verifyData(customerArray);
        if (!result.success) {
          ctx.logger.error('---------_handleAccountData ******* verify error ****** 处理account---- ' + accountDoc.account);
          return;
        }
        // 修改account数据
        await app.commonDB.db(app.constants.BILL).collection(app.constants.DB_PLATFORM_ACCOUNT_PRODUCT)
          .updateOne({_id: accountDoc._id}, {$set: {readEs: true}});
        ctx.logger.info('---------_handleAccountData ========== SUCCESS ========= ACCOUNT---- ' + accountDoc.account);
      });
    } catch (e) {
      ctx.logger.error('---------_handleAccountData-----error----' + e);
    }
  }

  private async _rebuildCustomerIndex(customers: any[]) {
    const { ctx } = this;
    const array: any[] = [];
    for (const customer of customers) {
      customer.account = customer.accountId;
      delete customer.accountId;
      if (customer.phone && customer.phone instanceof Array && customer.phone.length > 0) {
        customer.phone = customer.phone.map((d) => d.tel);
      }
      array.push(customer);
    }
    if (array.length > 0) {
      await ctx.service.customer.es.batchAddIndex2Cust(array);
    }
  }

  private async verifyData(customers: any[]) {
    const { ctx } = this;
    const result: any = {
      success: false,
    };
    let flag: boolean = false;
    try {
      // 先睡眠1s钟，以便数据完全写成功
      await promisify(setTimeout)(5 * 1000);
      // 从查询出的customer数据中取出5条数据进行查询验证
      customers = _.shuffle(customers);
      for (let i = 0 ; i < 5; i++) {
        if (customers[i] && customers[i].name) {
          const res: any = await ctx.service.customer.es.queryName(customers[i].name, customers[i].account, customers[i]._id);
          if (res.success) {
            flag = true;
            break;
          } else {
            const resPhone: any = await ctx.service.customer.es.queryPhone(customers[i].phone, customers[i].account, customers[i]._id);
            if (resPhone.success) {
              flag = true;
              break;
            }
          }
        }
      }
      if (flag) {
        result.success = true;
      }
    } catch (e) {
      ctx.logger.error('-------verifyData----' + e);
    }
    return result;
  }
}
